home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / video / fly8111-.000 / fly8111- / fly8 / remote.c < prev    next >
C/C++ Source or Header  |  1979-12-31  |  20KB  |  932 lines

  1. /* --------------------------------- remote.c ------------------------------- */
  2.  
  3. /* This is part of the flight simulator 'fly8'.
  4.  * Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au).
  5. */
  6.  
  7. /* Handler for the remote comms (very high level).
  8.  * This module is aware of the application data structures. It uses packet
  9.  * services to communicate with remotely participating programs.
  10. */
  11.  
  12. /* The timestamp must be moved to the beginning of the messages. This way
  13.  * out of order packets can be discarded. Right now it is too much bother
  14.  * to parse to the bottom of the message and then find out it is stale; too
  15.  * late!
  16. */
  17.  
  18. #include "fly.h"
  19.  
  20.  
  21. #define    COMM_VERSION    0x0007
  22.  
  23. #define    PACKHEADLEN    64
  24. #define    PAKGRAIN    32            /* must be power of 2 */
  25. #define    ONEPACKLEN    64            /* min pack len */
  26.  
  27. /* Our comms protocol. All message numbers should be >1 and <0xff
  28. */
  29.  
  30. #define    RC_MAINT    0x01
  31. #define    RC_ADD        0x02
  32. #define    RC_STAT        0x03
  33. #define    RC_URHIT    0x04
  34. #define    RC_IMHIT    0x05
  35. #define    RC_SHOOT    0x06
  36. #define    RC_TEXT        0x07
  37. #define    RC_TIMEREQ    0x08
  38. #define    RC_TIMEACK    0x0a
  39. #define    RC_ACTIVEQUERY    0x10        /* ping broadcast */
  40. #define    RC_ACTIVEREPLY    0x11        /* ping reply */
  41. #define    RC_NOTACTIVE    0x12        /* indicate going offline */
  42. #define    RC_REQUEST    0x13        /* request to play */
  43. #define    RC_REPLYPOS    0x14        /* accept player's request */
  44. #define    RC_REPLYNEG    0x15        /* announce 'not playing' */
  45.  
  46. /* Enforce consistent byte order in message data
  47. */
  48.  
  49. #define PUTINIT \
  50.     if (!(st.network & NET_INITED)) \
  51.         return (1); \
  52.     if (!(pack = packet_new (-1, -1))) \
  53.         return (1); \
  54.     d = pack->raw
  55.  
  56. #define PUTBYTE(b)    (*d++ = (Uchar)(b))
  57. #define PUTWORD(w)    (t = (w), *d++ = (Uchar)(t>>8), *d++ = (Uchar)t)
  58. #define PUTLONG(w)    (lt = (w), *d++ = (Uchar)(lt>>24), \
  59.              *d++ = (Uchar)(lt>>16), *d++ = (Uchar)(lt>>8), \
  60.              *d++ = (Uchar)lt)
  61. #define    GETBYTE        (t = *d++)
  62. #define    GETWORD        (t = *d++<<8, t += *d++)
  63. #define    GETLONG        (lt = *d++, lt = (lt<<8)+*d++, lt = (lt<<8)+*d++, \
  64.              lt = (lt<<8)+*d++)
  65.  
  66. extern PACKET * FAR
  67. packet_new (short size, short hlen)
  68. {
  69.     PACKET    *pack;
  70.  
  71.     if (!NEW (pack))
  72.         return (0);
  73.  
  74.     if (size < 0)
  75.         size = ONEPACKLEN;
  76.     pack->length = size;
  77.  
  78.     if (hlen < 0)
  79.         hlen = PACKHEADLEN;
  80.     size = ((size + hlen) + PAKGRAIN-1) & ~(PAKGRAIN-1);
  81.     pack->size = size;
  82.  
  83.     if (!(pack->data = memory_alloc (size))) {
  84.         DEL (pack);
  85.         return (0);
  86.     }
  87.     pack->raw = pack->data + hlen;
  88.  
  89.     return (pack);
  90. }
  91.  
  92. extern PACKET * FAR
  93. packet_del (PACKET *pack)
  94. {
  95.     memory_free (pack->data, pack->size);
  96.     return (DEL (pack));
  97. }
  98.  
  99. extern int FAR
  100. crc (PACKET *pack)
  101. {
  102.     int    i, crc;
  103.     Uchar    *p;
  104.  
  105.     for (p = pack->raw, crc = i = pack->length-2; i-- > 0;)
  106.         crc = (crc ^ (crc << 5)) ^ (int)*p++;
  107.     return (crc);
  108. }
  109.  
  110. LOCAL_FUNC int NEAR
  111. send_packet (PACKET *pack, Uchar *d, PLAYER *player)
  112. /*
  113.  * mode depends on 'player':
  114.  *    player        send only to this player
  115.  *    all_active    send to all PL_ACTIVE players
  116.  *    all_team    send to all players on my team
  117.  *    all_known    send to all known players
  118.  *    all_pports    broadcast to all netports with players
  119.  *    all_ports    broadcast to all netports
  120.  *    0        (invalid)
  121. */
  122. {
  123.     PLAYER    *pl;
  124.     int    t, ret;
  125.  
  126.     pack->length = (d - pack->raw) + 2;
  127.     if ((Uint)pack->length > pack->size) {
  128.         MsgEPrintf (-100, "Packet %02x too long (%d)",
  129.                 pack->raw[0], pack->length);
  130.         packet_del (pack);
  131.         return (1);
  132.     }
  133.     PUTWORD (crc (pack));
  134.  
  135.     if (player == st.all_ports && !(st.network & NET_NOBCAST))
  136.         ret = packet_send (pack, 1);
  137.     else if (player == st.all_pports && !(st.network & NET_NOBCAST))
  138.         ret = packet_send (pack, 2);
  139.     else if (player == st.all_known || player == st.all_active ||
  140.                             player == st.all_team){
  141.         ret = 0;
  142.         for (pl = 0; T(pl = player_next (pl));) {
  143.             if (player == st.all_active && !(pl->flags & PL_SEND))
  144.                 continue;
  145.             if (player == st.all_team &&
  146.                     stricmp (pl->team, st.teamname))
  147.                 continue;
  148.             pack->netport = pl->netport;
  149.             pack->address = pl->address;
  150.             if (T(ret = packet_send (pack, 0)))
  151.                 break;
  152.         }
  153.     } else if (player) {
  154.         pack->netport = player->netport;
  155.         pack->address = player->address;
  156.         ret = packet_send (pack, 0);
  157.     } else
  158.         ret = 1;        /* should not happen */
  159.     packet_del (pack);
  160.     return (ret);
  161. }
  162.  
  163. LOCAL_FUNC int NEAR
  164. send_command (int command, PLAYER *player)
  165. {
  166.     PACKET    *pack;
  167.     Uchar    *d;
  168.  
  169.     PUTINIT;
  170.     PUTBYTE (command);
  171.  
  172.     return (send_packet (pack, d, player));
  173. }
  174.  
  175. LOCAL_FUNC int NEAR
  176. send_stat (int command, OBJECT *p, PLAYER *player)
  177. {
  178.     int    t;
  179.     long    lt;
  180.     PACKET    *pack;
  181.     Uchar    *d;
  182.  
  183.     PUTINIT;
  184.     PUTBYTE (command);
  185.     PUTLONG (p->id);
  186.     PUTWORD (p->name);
  187.     PUTWORD (p->flags);
  188.     PUTWORD (p->gpflags);
  189.     PUTWORD (p->color);
  190.     PUTWORD (p->damage);
  191.     PUTWORD (p->a[X]);
  192.     PUTWORD (p->a[Y]);
  193.     PUTWORD (p->a[Z]);
  194.     PUTWORD (p->da[X]);
  195.     PUTWORD (p->da[Y]);
  196.     PUTWORD (p->da[Z]);
  197.     PUTLONG (p->R[X]);
  198.     PUTLONG (p->R[Y]);
  199.     PUTLONG (p->R[Z]);
  200.     PUTWORD (p->V[X]);
  201.     PUTWORD (p->V[Y]);
  202.     PUTWORD (p->V[Z]);
  203.     PUTWORD (p->speed);
  204.     PUTLONG (st.present);
  205.  
  206.     return (send_packet (pack, d, player));
  207. }
  208.  
  209. LOCAL_FUNC int NEAR
  210. send_maint (int command, OBJECT *p, PLAYER *player)
  211. {
  212.     int    t;
  213.     long    lt;
  214.     PACKET    *pack;
  215.     Uchar    *d;
  216.  
  217.     PUTINIT;
  218.     PUTBYTE (command);
  219.     PUTLONG (p->id);
  220.     PUTWORD (p->a[X]);
  221.     PUTWORD (p->a[Y]);
  222.     PUTWORD (p->a[Z]);
  223.     PUTLONG (p->R[X]);
  224.     PUTLONG (p->R[Y]);
  225.     PUTLONG (p->R[Z]);
  226.     PUTWORD (p->V[X]);
  227.     PUTWORD (p->V[Y]);
  228.     PUTWORD (p->V[Z]);
  229.     PUTLONG (st.present);
  230.  
  231.     return (send_packet (pack, d, player));
  232. }
  233.  
  234. extern int FAR
  235. remote_urhit (OBJECT *p, int speed, int extent, int damaging)
  236. {
  237.     int    t;
  238.     long    lt;
  239.     PACKET    *pack;
  240.     Uchar    *d;
  241.  
  242.     PUTINIT;
  243.     PUTBYTE (RC_URHIT);
  244.     PUTLONG (p->rid);
  245.     PUTWORD (speed);
  246.     PUTWORD (extent);
  247.     PUTWORD (damaging);
  248.  
  249.     return (send_packet (pack, d, p->rplayer));
  250. }
  251.  
  252. extern int FAR
  253. remote_imhit (OBJECT *p, int seed, int speed, int extent, int damaging)
  254. {
  255.     int    t;
  256.     long    lt;
  257.     PACKET    *pack;
  258.     Uchar    *d;
  259.  
  260.     PUTINIT;
  261.     PUTBYTE (RC_IMHIT);
  262.     PUTLONG (p->id);
  263.     PUTWORD (seed);
  264.     PUTWORD (speed);
  265.     PUTWORD (extent);
  266.     PUTWORD (damaging);
  267.  
  268.     return (send_packet (pack, d, st.all_pports));
  269. }
  270.  
  271. LOCAL_FUNC int NEAR
  272. send_shoot (OBJECT *p, int weapon, int n, int seed, int interval)
  273. {
  274.     int    t;
  275.     long    lt;
  276.     PACKET    *pack;
  277.     Uchar    *d;
  278.  
  279.     PUTINIT;
  280.     PUTBYTE (RC_SHOOT);
  281.     PUTLONG (p->id);
  282.     PUTWORD (weapon);
  283.     PUTWORD (n);
  284.     PUTWORD (seed);
  285.     PUTWORD (interval);
  286.  
  287.     return (send_packet (pack, d, st.all_pports));
  288. }
  289.  
  290. LOCAL_FUNC int NEAR
  291. send_playing (int command, PLAYER *player)
  292. {
  293.     int    t;
  294.     long    lt;
  295.     PACKET    *pack;
  296.     Uchar    *d;
  297.  
  298.     PUTINIT;
  299.     PUTBYTE (command);
  300.     PUTWORD (st.ComVersion);
  301.     PUTLONG (st.present);
  302.     strcpy ((char *)d, st.nikname);
  303.     d += strlen (st.nikname)+1;
  304.     strcpy ((char *)d, st.teamname);
  305.     d += strlen (st.teamname)+1;
  306.  
  307.     return (send_packet (pack, d, player));
  308. }
  309.  
  310. LOCAL_FUNC int NEAR
  311. send_text (char *text, PLAYER *player)
  312. {
  313.     int    t;
  314.     PACKET    *pack;
  315.     Uchar    *d;
  316.     int    len;
  317.  
  318.     PUTINIT;
  319.     PUTBYTE (RC_TEXT);
  320.     t = pack->size - 1 - 1 - 2;    /* cmd, text, eol, crc */
  321.     if ((len = strlen (text)) > t)
  322.         len = t;
  323.     memcpy (d, text, len);
  324.     d += len;
  325.     *d++ = '\0';
  326.  
  327.     return (send_packet (pack, d, player));
  328. }
  329.  
  330. LOCAL_FUNC int NEAR
  331. send_time (int command, PLAYER *player, Ulong time)
  332. {
  333.     long    lt;
  334.     PACKET    *pack;
  335.     Uchar    *d;
  336.  
  337.     PUTINIT;
  338.     PUTBYTE (command);
  339.     PUTLONG (time);
  340.  
  341.     return (send_packet (pack, d, player));
  342. }
  343.  
  344. extern int FAR
  345. send_obj (OBJECT *p, PLAYER *player)
  346. {
  347.     if (!(st.network & NET_INITED))
  348.         return (1);
  349.     if (!p) {
  350.         packet_send (0, 1);    /* flush all ports */
  351.         return (0);
  352.     }
  353.  
  354.     if (p->flags & F_NEW)
  355.         return (send_stat (RC_ADD, p, player));
  356.     else if (p->flags & F_MOD)
  357.         return (send_stat (RC_STAT, p, player));
  358.     else if (p->flags & F_MAINT)
  359.         return (send_maint (RC_MAINT, p, player));
  360.     else
  361.         return (0);
  362. }
  363.  
  364. LOCAL_FUNC int NEAR
  365. send_state (PLAYER *player)
  366. {
  367.     OBJECT    *p;
  368.  
  369.     for (p = CO; p; p = p->next) {
  370.         if (p->flags & F_EXPORTED)
  371.             send_stat (RC_ADD, p, player);
  372.     }
  373.     return (0);
  374. }
  375.  
  376. #define MAX_TIME_ERR    4096    /* integrated error high watermark */
  377.  
  378. LOCAL_FUNC void NEAR
  379. update_rtime (OBJECT *p, PLAYER *pl, PACKET *pack, Ulong rtime)
  380. {
  381.     if (EIM(p) && EIM(p)->lasttime > rtime)
  382.         ++STATS_NETERROOO;    /* out of order! */
  383.  
  384.     p->rtime = rtime - pl->rtime;            /* object currency */
  385.     pl->rtimeErr += (int)(p->rtime - pack->arrived);/* time diff err */
  386.     if (pl->rtimeErr > MAX_TIME_ERR) {
  387.         ++pl->rtime;
  388.         pl->rtimeErr /= 2;
  389.     } else if (pl->rtimeErr < -MAX_TIME_ERR) {
  390.         --pl->rtime;
  391.         pl->rtimeErr /= 2;
  392.     }
  393. }
  394.  
  395. /* process object-specific messages from a player.
  396. */
  397.  
  398. LOCAL_FUNC void NEAR
  399. receive_object (OBJECT *p)
  400. {
  401.     int    t;
  402.     long    lt;
  403.     PACKET    *pack, *next, *prev;
  404.     PLAYER    *pl;
  405.     Uchar    *d;
  406.     int    seed, speed, extent, n, weapon, damaging, count;
  407.  
  408.     if (!(pl = p->rplayer))
  409.         return;
  410.  
  411.     count = 0;
  412.     for (prev = 0, pack = pl->incoming; pack; prev = pack, pack = next) {
  413.         next = pack->next;
  414.         d = pack->raw;
  415.         switch (*d++) {        /* command */
  416.         case RC_STAT:
  417.             GETLONG;
  418.             if (p->rid != lt)
  419.                 continue;
  420.             ++count;
  421.             GETWORD;    p->name = t;
  422.             GETWORD;
  423.                 p->flags = F_IMPORTED|F_ALIVE|
  424.                     (t & ~(F_EXPORTED|F_MOD|F_DONE|F_FRIEND));
  425.             GETWORD;    n = p->gpflags;
  426.                     p->gpflags = t;
  427.             GETWORD;    p->color = t;
  428.             GETWORD;    p->damage = t;
  429.             GETWORD;    p->a[X] = t;
  430.             GETWORD;    p->a[Y] = t;
  431.             GETWORD;    p->a[Z] = t;
  432.             GETWORD;    p->da[X] = t;
  433.             GETWORD;    p->da[Y] = t;
  434.             GETWORD;    p->da[Z] = t;
  435.             GETLONG;    p->R[X] = lt;
  436.             GETLONG;    p->R[Y] = lt;
  437.             GETLONG;    p->R[Z] = lt;
  438.             GETWORD;    p->V[X] = t;
  439.             GETWORD;    p->V[Y] = t;
  440.             GETWORD;    p->V[Z] = t;
  441.             GETWORD;    p->speed = t;
  442.             GETLONG;    update_rtime (p, pl, pack, (Ulong)lt);
  443.  
  444.             Mobj (p);
  445.             p->time = FOREVER;
  446.             if (EIM(p))
  447.                 EIM(p)->timeout = st.ObjectTimeout;
  448.  
  449.             if (p->flags & F_CC) {
  450.                 if (pl->flags & PL_FRIEND) {
  451.                     p->color = ST_FRIEND;
  452.                     p->flags |= F_FRIEND;
  453.                 } else
  454.                     p->color = ST_FOE;
  455.             }
  456.  
  457.             break;
  458.  
  459.         case RC_MAINT:
  460.             GETLONG;
  461.             if (p->rid != lt)
  462.                 continue;
  463.             ++count;
  464.             GETWORD;    p->a[X] = t;
  465.             GETWORD;    p->a[Y] = t;
  466.             GETWORD;    p->a[Z] = t;
  467.             GETLONG;    p->R[X] = lt;
  468.             GETLONG;    p->R[Y] = lt;
  469.             GETLONG;    p->R[Z] = lt;
  470.             GETWORD;    p->V[X] = t;
  471.             GETWORD;    p->V[Y] = t;
  472.             GETWORD;    p->V[Z] = t;
  473.             GETLONG;    update_rtime (p, pl, pack, (Ulong)lt);
  474.  
  475.             Mobj (p);
  476.             p->da[X] = p->da[Y] = p->da[Z] = 0;
  477.             p->speed = ihypot3d (p->V);
  478.             p->flags |= F_ALIVE;
  479.             if (EIM(p))
  480.                 EIM(p)->timeout = st.ObjectTimeout;
  481.             break;
  482.  
  483.         case RC_IMHIT:
  484.             GETLONG;
  485.             if (p->rid != lt)
  486.                 continue;
  487.             ++count;
  488.             GETWORD;    seed = t;
  489.             GETWORD;    speed = t;
  490.             GETWORD;    extent = t;
  491.             GETWORD;    damaging = t;
  492.             object_hit (p, seed, speed, extent, damaging);
  493.             break;
  494.  
  495.         case RC_SHOOT:
  496.             GETLONG;
  497.             if (p->rid != lt)
  498.                 continue;
  499.             ++count;
  500.             GETWORD;    weapon = t;
  501.             GETWORD;    n = t;
  502.             GETWORD;    seed = t;
  503.             GETWORD;    speed = t;    /* interval */
  504.             shoot (p, weapon, n, seed, speed);
  505.             break;
  506.  
  507.         default:
  508.             continue;
  509.         }
  510.         if (prev)
  511.             prev->next = next;
  512.         else
  513.             pl->incoming = next;
  514.         packet_del (pack);
  515.         pack = prev;        /* prepare for 'prev = pack' */
  516.     }
  517.     pl->tail = prev;
  518.     if (count)
  519.         pl->timeout = st.PlayerTimeout;
  520. }
  521.  
  522. /* process general messages from a player.
  523. */
  524.  
  525. LOCAL_FUNC void NEAR
  526. receive_player (PLAYER *pl, int mode)
  527. {
  528.     int    t;
  529.     long    lt;
  530.     PACKET    *pack, *next, *prev;
  531.     OBJECT    *p;
  532.     Uchar    *d;
  533.     int    speed, extent, count, damaging;
  534.     long    rid;
  535.     char    msg[LADDRESS*2+1], *m;
  536.  
  537.     count = 0;
  538.     for (prev = 0, pack = pl->incoming; pack; prev = pack, pack = next) {
  539.         next = pack->next;
  540.         d = pack->raw;
  541.         switch (*d++) {        /* command */
  542.         case RC_URHIT:
  543.             ++count;
  544.             if (!(pl->flags & PL_RECEIVE))
  545.                 break;
  546.             GETLONG;
  547.             for (p = CO; p; p = p->next)
  548.                 if ((p->flags & F_EXPORTED) && p->id == lt)
  549.                     break;
  550.             if (p) {
  551.                 GETWORD;    speed = t;
  552.                 GETWORD;    extent = t;
  553.                 GETWORD;    damaging = t;
  554.                 object_hit (p, Frand(), speed, extent,
  555.                     damaging);
  556.             }
  557.             break;
  558.  
  559.         case RC_STAT:
  560.             if (!mode)
  561.                 continue;
  562.             ++count;
  563.             if (!(pl->flags & PL_RECEIVE))
  564.                 break;
  565.             ++STATS_NETERRFOUND;    /* was lost, now found! */
  566.             goto refresh;
  567.         case RC_ADD:
  568.             ++count;
  569.             if (!(pl->flags & PL_RECEIVE))
  570.                 break;
  571. refresh:
  572.             GETLONG;    rid = lt;
  573.             GETWORD;
  574.  
  575.             if (!(p = create_object (t, 0)))
  576.                 break;
  577.  
  578.             p->rplayer = pl;
  579.             p->rid = rid;
  580.             GETWORD;
  581.                 p->flags = F_IMPORTED|F_ALIVE|
  582.                     (t & ~(F_EXPORTED|F_MOD|F_DONE|F_FRIEND));
  583.             GETWORD;    p->gpflags = t;
  584.             GETWORD;    p->color = t;
  585.             GETWORD;    p->damage = t;
  586.             GETWORD;    p->a[X] = t;
  587.             GETWORD;    p->a[Y] = t;
  588.             GETWORD;    p->a[Z] = t;
  589.             GETWORD;    p->da[X] = t;
  590.             GETWORD;    p->da[Y] = t;
  591.             GETWORD;    p->da[Z] = t;
  592.             GETLONG;    p->R[X] = lt;
  593.             GETLONG;    p->R[Y] = lt;
  594.             GETLONG;    p->R[Z] = lt;
  595.             GETWORD;    p->V[X] = t;
  596.             GETWORD;    p->V[Y] = t;
  597.             GETWORD;    p->V[Z] = t;
  598.             GETWORD;    p->speed = t;
  599.             GETLONG;    update_rtime (p, pl, pack, (Ulong)lt);
  600.  
  601.             Mobj (p);
  602.             p->time = FOREVER;
  603.             if (T(NEW (EIM(p)))) {
  604.                 p->e_type = ET_IMPORTED;
  605.                 EIM(p)->timeout = st.ObjectTimeout;
  606.             }
  607.  
  608.             if (p->flags & F_CC) {
  609.                 if (pl->flags & PL_FRIEND) {
  610.                     p->color = ST_FRIEND;
  611.                     p->flags |= F_FRIEND;
  612.                 } else
  613.                     p->color = ST_FOE;
  614.             }
  615.  
  616.             break;
  617.  
  618.         case RC_ACTIVEQUERY:            /* idle -> active */
  619.             GETWORD;            /* version */
  620.             pl->ComVersion = (Uint)t;
  621.             if (pl->ComVersion < 7) {    /* obsolete */
  622.                 MsgWPrintf (100, "old ComVer %u: %s:%s",
  623.                     (Uint)t, pl->name, pl->team);
  624.                 break;
  625.             }
  626.             send_playing (RC_ACTIVEREPLY, pl);
  627.             goto common_playing;
  628.  
  629.         case RC_ACTIVEREPLY:            /* idle -> active */
  630.             GETWORD;            /* version */
  631.             pl->ComVersion = (Uint)t;
  632.             if (pl->ComVersion < 5) {    /* obsolete */
  633.                 MsgWPrintf (100, "ComVer %u: %s:%s",
  634.                     (Uint)t, pl->name, pl->team);
  635.                 break;
  636.             }
  637. common_playing:
  638.             GETLONG;
  639.             if (!(pl->flags & PL_PLAYING)) {
  640.                 pl->rtime = lt - pack->arrived;
  641.                 pl->rtimeErr = 0L;
  642.             }
  643.             ++count;
  644.             strncpy (pl->name, (char *)d, LNAME);
  645.             if (pl->ComVersion >= 6) {
  646.                 d += strlen ((char *)d) + 1;
  647.                 strncpy (pl->team, (char *)d, LNAME);
  648.                 if (!stricmp (pl->team, st.teamname))
  649.                     pl->flags |= PL_FRIEND;
  650.                 else
  651.                     pl->flags &= ~PL_FRIEND;
  652.             } else
  653.                 strncpy (pl->team, "[old]", LNAME);
  654.             if (pl->flags & PL_PLAYING)
  655.                 break;
  656.             if (pl->flags & (PL_NOTIDLE & ~PL_ACTIVE))
  657.                 ;
  658.             else {
  659.                 MsgWPrintf (100, "Active: %s:%s",
  660.                     pl->name, pl->team);
  661.                 for (m = msg, t = 0; t < LADDRESS; ++t) {
  662.                     sprintf (m, "%02x", pl->address[t]);
  663.                     m += 2;
  664.                 }
  665.                 MsgPrintf (100, "Addr:   %s", msg);
  666.             }
  667.             if (st.network & NET_AUTOCONNECT)
  668.                 remote_request (pl);
  669.             break;
  670.  
  671.         case RC_NOTACTIVE:            /* active -> idle */
  672.             ++count;
  673.             LogPrintf ("%s ", Tm->Ctime ());
  674.             MsgWPrintf (-100, "Gone: %s:%s", pl->name, pl->team);
  675.             player_remove (pl);
  676.             pl->flags &= ~PL_NOTIDLE;
  677.             break;
  678.  
  679.         case RC_REQUEST:            /* active -> pend */
  680.             ++count;
  681.             MsgPrintf (100, "Asking: %s:%s", pl->name, pl->team);
  682.             if (pl->flags & PL_NOTIDLE) {
  683.                 player_remove (pl);
  684.                 pl->flags &= ~PL_NOTIDLE;
  685.             }
  686.             pl->flags |= PL_PENDBOSS;
  687.             if (st.network & NET_AUTOACCEPT)
  688.                 remote_reply (pl, 1);
  689.             else if (st.network & NET_AUTODECLINE)
  690.                 remote_reply (pl, 0);
  691.             else
  692.                 MsgWPrintf (100, "Pending: %s:%s",
  693.                     pl->name, pl->team);
  694.             break;
  695.  
  696.         case RC_REPLYPOS:        /* pend -> play */
  697.             ++count;
  698.             if (!(pl->flags & PL_PEND))
  699.                 break;
  700.             if (pl->flags & PL_PENDREQUEST)
  701.                 send_command (RC_REPLYPOS, pl);
  702.             pl->flags &= ~PL_PEND;
  703.             pl->flags |= PL_PLAYING;
  704.             netport_count (pl, 1);
  705.             send_state (pl);
  706.             LogPrintf ("%s ", Tm->Ctime ());
  707.             MsgWPrintf (-100, "Joined: %s:%s", pl->name, pl->team);
  708.             MsgWPrintf (-100, "  thru  %s",
  709.                 netport_name (pl->netport));
  710.             MsgWPrintf (-100, "  addr  %s",
  711.                 netport_addr (pl->netport, pl->address));
  712.             break;
  713.  
  714.         case RC_REPLYNEG:        /* pend/playing -> active */
  715.             ++count;
  716.             if (pl->flags & PL_PEND)
  717.                 MsgWPrintf (100, "Declined: %s:%s",
  718.                     pl->name, pl->team);
  719.             else if (pl->flags & PL_PLAYING) {
  720.                 LogPrintf ("%s ", Tm->Ctime ());
  721.                 MsgWPrintf (-100, "Not Playing: %s:%s",
  722.                     pl->name, pl->team);
  723.             }
  724.             player_remove (pl);
  725.             pl->flags &= ~PL_NOTIDLE;
  726.             pl->flags |= PL_ACTIVE;
  727.             break;
  728.  
  729.         case RC_TEXT:
  730.             ++count;
  731.             if (strlen ((char *)d) > 80)
  732.                 break;
  733.             MsgWPrintf (100, "%s:%s says:", pl->name, pl->team);
  734.             MsgWPrintf (100, "  %s", d);
  735.             break;
  736.  
  737.         case RC_TIMEREQ:
  738.             ++count;
  739.             GETLONG;            /* remote send time */
  740.             send_time (RC_TIMEACK, pl, lt);
  741.             break;
  742.  
  743.         case RC_TIMEACK:
  744.             ++count;
  745.             GETLONG;            /* my send time */
  746.             MsgPrintf (100, "%s:%s time: %lu",
  747.                 pl->name, pl->team, Tm->Milli () - lt);
  748.             break;
  749.  
  750.         default:
  751.             continue;
  752.         }
  753.         if (prev)
  754.             prev->next = next;
  755.         else
  756.             pl->incoming = next;
  757.         packet_del (pack);
  758.         pack = prev;        /* prepare for 'prev = pack' */
  759.     }
  760.     pl->tail = prev;
  761.     if (count)
  762.         pl->timeout = st.PlayerTimeout;
  763. }
  764.  
  765. extern void FAR
  766. remote_receive (OBJECT *obj)
  767. {
  768.     PLAYER    *pl;
  769.  
  770.     if (!(st.network & NET_INITED))
  771.         return;
  772.  
  773.     if (obj)
  774.         receive_object (obj);
  775.     else {
  776.         netports_receive ();
  777.         for (pl = 0; T(pl = player_next (pl));)
  778.             receive_player (pl, 0);
  779.     }
  780. }
  781.  
  782. extern void FAR
  783. remote_refresh (void)
  784. {
  785.     PLAYER    *pl;
  786.  
  787.     if (!(st.network & NET_INITED))
  788.         return;
  789.  
  790.     for (pl = 0; T(pl = player_next (pl));)
  791.         receive_player (pl, 1);
  792. }
  793.  
  794. extern void FAR
  795. remote_request (PLAYER *pl)
  796. {
  797.     if (pl->flags & PL_PLAYING)
  798.         MsgPrintf (100, "already playing: %s:%s", pl->name, pl->team);
  799.     else {
  800.         MsgPrintf (50, "Requesting %s:%s", pl->name, pl->team);
  801.         send_command (RC_REQUEST, pl);
  802.         pl->flags &= ~PL_NOTIDLE;
  803.         pl->flags |= PL_PENDREQUEST;
  804.         pl->timeout = st.PlayerTimeout;
  805.     }
  806. }
  807.  
  808. extern void FAR
  809. remote_reply (PLAYER *pl, int reply)
  810. {
  811.     if (!(pl->flags & PL_PENDBOSS)) {
  812.         MsgPrintf (100, "not pending");
  813.         return;
  814.     }
  815.     pl->flags &= ~PL_PEND;
  816.     if (reply) {
  817.         MsgPrintf (100, "Accepting: %s:%s", pl->name, pl->team);
  818.         pl->flags |= PL_PENDCONFIRM;
  819.         send_command (RC_REPLYPOS, pl);
  820.     } else {
  821.         MsgPrintf (100, "Declining: %s:%s", pl->name, pl->team);
  822.         send_command (RC_REPLYNEG, pl);
  823.     }
  824. }
  825.  
  826. extern void FAR
  827. remote_noplay (PLAYER *pl)
  828. {
  829.     if (st.network & NET_INITED)
  830.         send_command (RC_REPLYNEG, pl);
  831. }
  832.  
  833. extern void FAR
  834. remote_ping (void)
  835. {
  836.     if (st.network & NET_INITED)
  837.         send_playing (RC_ACTIVEQUERY, st.all_ports);
  838. }
  839.  
  840. extern void FAR
  841. remote_shoot (OBJECT *p, int weapon, int n, int seed, int interval)
  842. {
  843.     if (st.network & NET_INITED)
  844.         send_shoot (p, weapon, n, seed, interval);
  845. }
  846.  
  847. extern void FAR
  848. remote_msg (char *text, PLAYER *pl)
  849. {
  850.     if (st.network & NET_INITED)
  851.         send_text (text, pl);
  852. }
  853.  
  854. extern void FAR
  855. remote_time (PLAYER *pl)
  856. {
  857.     if (st.network & NET_INITED)
  858.         send_time (RC_TIMEREQ, pl, Tm->Milli ());
  859. }
  860.  
  861. extern int FAR
  862. remote_init (void)
  863. {
  864.     if (!(st.network & NET_ON))
  865.         return (0);
  866.  
  867.     st.ComVersion = COMM_VERSION;
  868.     MsgPrintf (-100, "Net Ver  %u", (int)st.ComVersion);
  869.  
  870.     st.all_known   = ((PLAYER NEAR *)0)+1;
  871.     st.all_active  = ((PLAYER NEAR *)0)+2;
  872.     st.all_team    = ((PLAYER NEAR *)0)+3;
  873.     st.all_ports   = ((PLAYER NEAR *)0)+4;
  874.     st.all_pports  = ((PLAYER NEAR *)0)+5;
  875.     st.all_players = ((PLAYER NEAR *)0)+6;
  876.     st.no_players  = ((PLAYER NEAR *)0)+7;
  877.  
  878.     if (netports_init ())
  879.         return (1);
  880.  
  881.     if (players_init ())
  882.         return (1);
  883.     st.network |= NET_INITED;
  884.     return (0);
  885. }
  886.  
  887. extern void FAR
  888. remote_term (void)
  889. {
  890.     if (!(st.network & NET_INITED))
  891.         return;
  892.  
  893.     send_command (RC_NOTACTIVE, st.all_ports);
  894.     players_term ();
  895.     netports_term ();
  896.  
  897.     if (STATS_NETERRLOW[1])
  898.         LogPrintf ("in  av %lu max %lu\n",
  899.             STATS_NETERRLOW[2]/STATS_NETERRLOW[0],
  900.             STATS_NETERRLOW[1]);
  901.     if (STATS_NETERRLOW[4])
  902.         LogPrintf ("out av %lu max %lu\n",
  903.             STATS_NETERRLOW[5]/STATS_NETERRLOW[3],
  904.             STATS_NETERRLOW[4]);
  905.     st.network &= ~NET_INITED;
  906. }
  907.  
  908. #undef COMM_VERSION
  909. #undef RC_MAINT
  910. #undef RC_ADD
  911. #undef RC_STAT
  912. #undef RC_URHIT
  913. #undef RC_IMHIT
  914. #undef RC_SHOOT
  915. #undef RC_TEXT
  916. #undef RC_TIMEREQ
  917. #undef RC_TIMEACK
  918. #undef RC_ACTIVEQUERY
  919. #undef RC_ACTIVEREPLY
  920. #undef RC_NOTACTIVE
  921. #undef RC_REQUEST
  922. #undef RC_REPLYPOS
  923. #undef RC_REPLYNEG
  924. #undef PUTINIT
  925. #undef PUTBYTE
  926. #undef PUTWORD
  927. #undef PUTLONG
  928. #undef GETBYTE
  929. #undef GETWORD
  930. #undef GETLONG
  931. #undef MAX_TIME_ERR
  932.